/*
 * @Description: 城市转移
 * @Author: zy
 * @Date: 2021-06-07 09:04:21
 * @LastEditors: zy
 * @LastEditTime: 2021-06-09 20:29:55
 */
import * as d3 from 'd3'
export class CityTransfer {
  chart = {}
  layout = {}
  _rowData = ''
  constructor(divId, vue) {
    this.divId = divId
    this.vue = vue
  }
  initChart(divId) {
    this.layout.padding = {
      left: 40,
      right: 10,
      top: 40,
      bottom: 10
    }

    this.layout.divHeight = document.getElementById(divId).offsetHeight -
      this.layout.padding.top -
      this.layout.padding.bottom
    this.layout.divWidth = document.getElementById(divId).offsetWidth -
      this.layout.padding.left -
      this.layout.padding.right

    this.chart.svg = d3
      .select('#' + divId)
      .append('svg')
      .attr('width', this.layout.divWidth +
        this.layout.padding.left +
        this.layout.padding.right
      )
      .attr('height', this.layout.divHeight +
        this.layout.padding.top +
        this.layout.padding.bottom
      )
      .attr('class', 'cityTransfer')
  }
  initLayout(data) {
    let yDomain = ['长江中游城市群', '哈长城市群', '成渝城市群', '长江三角洲城市群', '中原城市群',
      '北部湾城市群', '关中平原城市群', '呼包鄂榆城市群', '兰西城市群', '粤港澳大湾区', '京津冀城市群',
      '辽中南城市群', '山东半岛城市群', '海峡西岸城市群']
    this.layout.color = function(name) {
      // let mycolor = ['#949483', '#f47b7b', '#9f1f5c', '#ef9020', '#00af3e',
      //   '#85b7e2', '#29245c', '#ffd616', '#e5352b', '#e990ab', '#0081b4',
      //   '#96cbb3', '#91be3e', '#39a6dd'
      // ]
      let newColor = ['#8db5d3', '#f7c3b0', '#a1ede9', '#ffa05a', '#c492fd', '#3baeff',
        '#aed8ff', '#69bcaf', '#f2e280', '#d4cff7', '#fa8170', '#8f89ff', '#93d47f', '#ffc34e']
      let colorScale = d3.scaleOrdinal()
        .domain(yDomain)
        .range(newColor)
      return colorScale(name)
    }
    let rDomain = d3.max(data, function(d) {
      return d3.max(d.data, function(o) {
        return +o.changeNum
      })
    })

    this.layout.cityCluster = yDomain
    let dateRange = data.map(d => d.date)
    this.layout.xScale = d3.scaleBand()
      .domain(dateRange)
      .range([this.layout.padding.left, this.layout.divWidth + this.layout.padding.left])

    this.layout.yScale = d3.scaleBand()
      .domain(yDomain)
      .range([this.layout.padding.top, this.layout.divHeight + this.layout.padding.top])

    this.layout.band = Math.min(this.layout.xScale.bandwidth(), this.layout.yScale.bandwidth())
    // console.log(this.layout.xScale.bandwidth(), this.layout.yScale.bandwidth(), this.layout.band)
    this.layout.rScale = d3.scaleLinear()
      .domain([0, rDomain])
      .range([0, this.layout.band])
  }
  normativeData(data, flag, fromCluster) {
    let norData = []
    this.layout.dateRange.forEach(function(d) {
      let allChange = 0
      let item = {'date': d, 'data': []}
      data.filter(function(o) {
        if (o.in_date === d) {
          item.data.push(o)
        }
      })
      let city = {}
      item.data.forEach(function(o) {
        if (o[flag] in city) { // in_city
          city[o[flag]].push(o)
        } else {
          city[o[flag]] = []
          city[o[flag]].push(o)
        }
      })
      let cityCluster = []
      for (let key in city) {
        let changeNum = 0
        let changes = city[key].map(function(o) {
          changeNum += o.change_city.length
          return {'fromClsuter': o[fromCluster], 'transfer': o.change_city, 'date': o.in_date}
        })
        cityCluster.push({
          'cluster': key,
          'date': city[key][0].in_date,
          'data': changes,
          changeNum: changeNum
        })
        allChange += changeNum
      }
      item.data = cityCluster
      item.allChange = allChange
      norData.push(item)
    })
    return norData
  }

  renderCluster() {
    let that = this
    let myCluster = this.chart.svg.select('.myCluster')
    if (myCluster.empty()) {
      myCluster = this.chart.svg.append('g')
        .attr('class', 'myCluster')
    }

    myCluster.selectAll('.cityCluster')
      .data(this.layout.cityCluster)
      .enter()
      .append('rect')
      .attr('class', 'cityCluster')
      .attr('x', this.layout.xScale(this.layout.dateRange[0]) - 3 * this.layout.band)
      .attr('y', d => this.layout.yScale(d))
      .attr('height', this.layout.band)
      .attr('width', this.layout.band)
      .style('stroke', 'black')
      .style('stroke-width', 1)
      .style('fill', d => this.layout.color(d))
      .style('opacity', 0.6)
      .on('click', function() {
        let dom = d3.select(this)
        if (parseFloat(dom.style('opacity')) === 0.6) {
          dom.style('opacity', 0.1)
        } else {
          dom.style('opacity', 0.6)
        }
        let selectedCluster = []
        that.chart.svg.selectAll('.cityCluster').each(function(_, i) {
          let dom = d3.select(this)
          if (parseFloat(dom.style('opacity')) === 0.6) {
            selectedCluster.push(i)
          }
        })
        that.vue.chart.parallelChart.filterByCluster(selectedCluster, 'category')
        that.vue.chart.steelChart.filterByCluster(selectedCluster)
        that.vue.chart.mapChart.showClusterCity(selectedCluster)

        // let data = that._rowData.filter(function(d) {
        //   let index = that.category.indexOf(d.in_city)
        //   if (selectedCluster.indexOf(index) !== -1) {
        //     return d
        //   }
        // })
        // that.update(data)
      })
      .append('title')
      .text(String)

    this.chart.svg.select('.myCluster')
      .append('rect')
      .attr('class', 'all')
      .attr('x', this.layout.xScale(this.layout.dateRange[0]) - 3 * this.layout.band)
      .attr('y', this.layout.padding.top - 2 * this.layout.band)
      .attr('height', this.layout.band)
      .attr('width', this.layout.band)
      .style('stroke', 'black')
      .style('stroke-width', 1)
      .style('fill', 'blue')
      .style('opacity', 0.6)
      .on('click', function() {
        let dom = d3.select(this)
        if (parseFloat(dom.style('opacity')) === 0.6) {
          dom.style('opacity', 0.1)
          that.chart.svg.selectAll('.cityCluster').style('opacity', 0.1)
        } else {
          dom.style('opacity', 0.6)
          that.chart.svg.selectAll('.cityCluster').style('opacity', 0.6)
        }
        let selectedCluster = []
        that.chart.svg.selectAll('.cityCluster').each(function(_, i) {
          let dom = d3.select(this)
          if (parseFloat(dom.style('opacity')) === 0.6) {
            selectedCluster.push(i)
          }
        })
        that.vue.chart.parallelChart.filterByCluster(selectedCluster, 'category')
        that.vue.chart.steelChart.filterByCluster(selectedCluster)
        that.vue.chart.mapChart.showClusterCity(selectedCluster)
      })
  }

  render(data) {
    this._rowData = data
    this.initChart(this.divId)
    let xDomain = []
    data.forEach(function(d) {
      if (xDomain.indexOf(d.in_date) === -1) {
        xDomain.push(d.in_date)
      }
    })

    this.layout.dateRange = xDomain
    let inData = this.normativeData(data, 'in_city', 'out_city')
    let outData = this.normativeData(data, 'out_city', 'in_city')
    inData = inData.filter(d => d.allChange >= 50)
    this.initLayout(inData)
    this.renderTransfer(inData)
    this.renderCluster()
    this.renderMaxOut(outData)
  }

  update(data) {
    // this.chart.svg.selectAll('.date').remove()
    let xDomain = []
    data.forEach(function(d) {
      if (xDomain.indexOf(d.in_date) === -1) {
        xDomain.push(d.in_date)
      }
    })
    this.layout.dateRange = xDomain
    let inData = this.normativeData(data, 'in_city', 'out_city')
    let outData = this.normativeData(data, 'out_city', 'in_city')
    inData = inData.filter(d => d.allChange >= 50)
    this.initLayout(inData)
    this.renderTransfer(inData)
    this.renderMaxOut(outData)
  }
  renderTransfer(norData) {
    let data = []
    norData.forEach(function(d) {
      data.push(...d.data)
    })

    let gTransfer = this.chart.svg
      .selectAll('.transfer')
      .data(data, d => d.date + '-' + d.cluster)

    gTransfer.transition()
      .duration(750)
      .attr('r', d => {
        return this.layout.rScale(d.changeNum)
      })
      .attr('cx', d => {
        return this.layout.xScale(d.date) + this.layout.band / 2
      })
      .attr('cy', d => this.layout.yScale(d.cluster) + this.layout.band / 2)

    let enterNode = gTransfer.enter()
      .append('circle')
      .attr('class', 'transfer')
      .attr('r', d => {
        return this.layout.rScale(d.changeNum)
      })
      .attr('cx', d => {
        return this.layout.xScale(d.date) + this.layout.band / 2
      })
      .attr('cy', d => this.layout.yScale(d.cluster) + this.layout.band / 2)
      .style('stroke', 'black')
      .style('stroke-width', 1)
      .style('fill', '#CDC9C9')
      .style('opacity', 0.6)
      .on('click', (_, d) => {
        this.vue.selectDate = d.date
        this.vue.dateChange()
        let transferCity = []
        d.data.forEach(function(o) {
          transferCity.push(...o['transfer'])
        })
        this.vue.chart.mapChart.showTransferCity(transferCity)
      })

    enterNode.append('title')
      .text(d => '名称: ' + d.cluster + '\n 转入的城市数量: ' + d.changeNum + '\n 日期: ' + d.date)

    gTransfer.exit()
      .transition()
      .duration(75)
      .attr('r', 0)
      .remove()
  }

  renderMaxOut(data) {
    let outMaxs = data.map(function(d) {
      let maxIndex = {}
      let maxValue = -1
      d.data.forEach(function(o) {
        if (o.changeNum > maxValue) {
          maxIndex = o
          maxValue = o.changeNum
        }
      })
      return maxIndex
    })
    let gmax = this.chart.svg.selectAll('.max')
      .data(outMaxs.filter(d => {
        if (this.layout.xScale(d.date) !== undefined) {
          return d
        }
      }))

    gmax.transition()
      .duration(750)
      .attr('x', d => {
        return this.layout.xScale(d.date)
      })
      .attr('y', this.layout.padding.top - 2 * this.layout.band)
      .attr('width', this.layout.band - 2)
      .attr('height', this.layout.band - 2)

    let enterNode = gmax.enter()
      .append('rect')
      .attr('class', 'max')
      .attr('x', d => {
        return this.layout.xScale(d.date)
      })
      .attr('y', this.layout.padding.top - 2 * this.layout.band)
      .attr('width', this.layout.band - 2)
      .attr('height', this.layout.band - 2)
      .style('stroke', 'black')
      .style('stroke-width', 1)
      .style('fill', d => this.layout.color(d.cluster))
      .style('opacity', 0.6)

    enterNode.append('title')
      .text(d => '转出数量最大的城市群: \n' + d.cluster + '\n' + '日期: ' + d.date)

    gmax.exit()
      .transition()
      .duration(750)
      .attr('width', 0)
      .attr('height', 0)
      .remove()
  }
}
